'use strict';

/**
 * gateway Module
 *
 * Description
 */
angular.module('sfhtHaitaoCmsApp')
  .service('Gateway', function($http, md5, store, $location, $cookies, $q, CONST_CMS_REQUEST_URL, CONST_DEFAULT_REQUEST_HEADER, TOKEN_AND_SIGNATURE_ERROR_GROUP, CONST_WEB_LOGIN_LINK, CONST_NONE_APPEND_WORD) {

    var SecurityType = {
      UserLogin: {
        name: 'UserLogin',
        code: 0x2000
      },
      RegisteredDevice: {
        name: 'RegisteredDevice',
        code: 0x0100
      },
      None: {
        name: 'None',
        code: 0
      }
    };

    var _aid = 301;
    var Gateway = function(options, data) {
      this.options = options;
      this.init(data);
    };

    Gateway.prototype = {

      /**
       * api的定义需要被每个子类复写
       * @type {Object}
       */
      api: {},

      /**
       * @function sf.b2c.mall.framework.comm.buildRequestData
       * @description 通过与定义的API接口和用户通过this.data传入的参数构建向服务端发起请求需要用到的数据
       * @return {Object} 向服务端提交的数据结构
       */
      buildRequestData: function() {
        if (this.options && this.options.api) {
          var requestData = {};

          // 添加每个请求的_mt参数
          _.extend(requestData, {
            '_mt': this.options.api.METHOD_NAME
          });

          // 提供公共参数
          _.extend(requestData, this.options.api.COMMON);

          var key;
          // 添加必填参数
          for (key in this.options.api.REQUIRED) {
            requestData[key] = this.data[key];
          }

          // 添加选填参数
          for (key in this.options.api.OPTIONAL) {
            requestData[key] = this.data[key];
          }

          return requestData;
        }
      },

      /**
       * @override
       * @function sf.b2c.mall.framework.comm.init
       * @description 初始化方法
       * @param  {Object} data 传入的涌来提交服务端的数据
       */
      init: function(data) {
        this.setData(data);
      },

      /**
       * @function sf.b2c.mall.framework.setData
       * @description 修改请求参数
       */
      setData: function(data) {
        this.data = data;
      },

      /**
       * @function sf.b2c.mall.framework.sendRequest
       * @description 构建请求
       * @param {boolean} isForceUserLogin 是否需要强制用户登录
       * @return {Object} can.Deferred
       */
      sendRequest: function(isForceUserLogin) {
        isForceUserLogin = true;
        //step1 调用子业务类进行数据校验
        var checkResult = this.validate(isForceUserLogin);

        if (checkResult !== true) {
          return checkResult;
        }

        //step2 构建ajax请求数据，放到baseCommon的全局变量中，可以支持多个请求一起发送
        var requestData = this.buildRequestData();

        //step3 发送请求,获得返回数据
        return this.request(requestData, isForceUserLogin);
      },

      /**
       * @function sf.b2c.framework.comm.validate
       * @description 根据用户SecurityType进行检验，同时也会检验比天字段是否写入
       * @returns {Error|Boolean} 错误对象|验证成功
       */
      validate: function(isForceUserLogin) {
        // 检查必填字段，如果没有必填字段直接抛错
        if (this.options && this.options.api) {
          if (!this.options.api.METHOD_NAME) return '缺少_mt';
          for (var key in this.options.api.REQUIRED) {
            if (!_.has(this.data, key)) {
              return new Error('缺少必填字段' + key);
            }
          }
        }
        //根据action校验是否登录
        //强制所有请求都登入
        // if (this.options.api.SECURITY_TYPE === SecurityType.UserLogin.name) {
        if (!this.checkUserLogin()) {
          if (isForceUserLogin) {
            this.goToLogin();
          } else {
            return new Error('该请求需要在登录后发起');
          }
        }
        // }

        return true;
      },

      /**
       * @function sf.b2c.mall.framework.checkUserLogin
       * @description 检查用户是否登陆
       * @return {Boolean} 用户是否登陆
       */
      checkUserLogin: function() {
        var csrf = store.get('csrfToken');
        return !!($cookies[_aid + '_ct'] && csrf);
      },

      /**
       * @function sf.b2c.mall.framework.goToLogin
       * @description 跳转到登陆
       */
      goToLogin: function() {
        // 获取现在的pathname作为跳转的from依据
        // var path = window.location.pathname;
        // if (path !== SFBizConfig.setting.login) {
        //   window.location.href = SFBizConfig.setting.login + '?from' + path;
        // }
        // $location.path(CONST_WEB_LOGIN_LINK + '?from' + path);
        window.location.href = CONST_WEB_LOGIN_LINK;
      },

      /**
       * @function sf.b2c.mall.framework.comm.access
       * @description 返回的参数是否正确
       * @param  {Map}      response          服务端返回的信息
       * @param  {Boolean}  isForceUserLogin  是否需要强制登陆
       */
      access: function(response, isForceUserLogin) {
        if (response.stat.code === 0 && response.content[0] && response.stat.stateList[0].code === 0) {
          return true;
        } else if (_.contains(TOKEN_AND_SIGNATURE_ERROR_GROUP, response.stat.code) && isForceUserLogin) {
          this.goToLogin();
        } else {
          return false;
        }
      },

      /**
       * @function sf.b2c.mall.framework.comm.encrypt
       * @param  {Map}    params      需要加密的参数
       * @param  {String} appendWord  加言
       */
      encrypt: function(params, appendWord) {
        var arr = [];

        // 将Map变成Array，使用key=value的方式进行拼接
        _.each(params, function(value, key) {
          arr.push(key + '=' + value);
        });

        // 以ascii进行排序
        arr.sort();

        // 将队列拼接成String
        var str = arr.join('');
        str = str + appendWord;

        // 做md5加密
        //return md5.createHash(str);
        return faultylabs.MD5(str);
      },

      /**
       * @function sf.b2c.mall.framework.comm.sign
       * @param  {Map}      params           参与请求签名的实体
       * @param  {Boolean}  isForceUserLogin 是否需要强制登陆
       */
      sign: function(params, isForceUserLogin) {
        var map = {
          'None': function(data, force) {
            return _.extend(data, {
              _sig: this.encrypt(data, CONST_NONE_APPEND_WORD)
            });
          },

          'RegisteredDevice': function(data, force) {
            return _.extend(data, {
              _sig: this.encrypt(data, CONST_NONE_APPEND_WORD)
            });
          },

          'UserLogin': function(data, force) {
            var csrf = store.get('csrfToken');

            if (csrf) {
              return _.extend(data, {
                _sig: this.encrypt(data, csrf)
              });
            } else {
              this.goToLogin();
            }
          }
        };

        if (_.isFunction(map[this.options.api.SECURITY_TYPE])) {
          // 过滤所有的undefined和null的数据
          _.each(params, function(value, key, list) {
            if (_.isUndefined(value) || _.isNull(value)) {
              delete params[key];
            }
          });

          // 将参数附加上必须要传递的标记
          var required = _.extend(params, CONST_DEFAULT_REQUEST_HEADER);
          required = _.extend(required, {
            _aid: _aid
          });

          // 做加密生产_sig对象
          var _sig = map[this.options.api.SECURITY_TYPE].call(this, required, isForceUserLogin);

          // 返回数据可以直接做请求
          return _.extend(required, _sig);
        } else {
          return params;
        }
      },

      /**
       * @function sf.b2c.mall.framework.request
       * @param  {Map}     data             请求参数
       * @param  {Boolean} isForceUserLogin 是否需要强制登陆
       * @return {can.Deferred}
       */
      request: function(data, isForceUserLogin) {
        var def = $q.defer();
        var that = this;
        // 没有使用$http而是使用了$.ajax是因为网关现在支持的只有form提交
        $.ajax({
            url: CONST_CMS_REQUEST_URL,
            type: 'post',
            data: that.sign(data)
          })
          .done(function(response) {
            if (response && response.stat) {
              that.serverTime = response.stat.systime;
            }
            if (that.access(response, isForceUserLogin)) {
              that.afterRequest(data._mt, response.content[0]);
              def.resolve(response.content[0]);
            } else {
              if (response.stat.stateList.length == 0) {
                def.reject(response.stat.code);
              } else {
                def.reject("code:" + response.stat.stateList[0].code + ",msg:" + response.stat.stateList[0].msg, response.stat.stateList[0].code);
              }
            }
          })
          .fail(function(error) {
            def.reject(error);
          });

        return def.promise;
      },

      /**
       * @description 通过服务端接口每次从stat中返回的system在客户端中保留服务端时间
       * @return {Int} 服务端时间的时间戳
       */
      getServerTime: function() {
        return this.serverTime;
      },

      /**
       * @description 请求后处理回调
       * @function sf.b2c.mall.framework.comm.afterRequest
       * @param  {String} mt
       * @param  {Map} response
       */
      afterRequest: function(mt, response) {
        var map = {
          'cms.webLogin': function(response) {
            store.set('csrfToken', response.csrfToken);
          },

          "cms.partnerLogin": function(response) {
            store.set('csrfToken', response.csrfToken);
          },

          "cms.mobileRegister": function(response) {
            store.set('csrfToken', response.csrfToken);
          }
        };

        if (_.isFunction(map[mt])) {
          map[mt].call(this, response);
        }
      }
    }
    return Gateway;
  })